package com.qfedu.fmmall.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.qfedu.fmmall.common.status.ResStatus;
import com.qfedu.fmmall.common.utils.MD5Utils;
import com.qfedu.fmmall.common.vo.ResultVO;
import com.qfedu.fmmall.dao.UsersMapper;
import com.qfedu.fmmall.entity.Users;
import com.qfedu.fmmall.service.UserService;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author : yanBin
 * @date :2021/12/3 9:48
 */
@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UsersMapper usersMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 登录
     *
     * @param username 账号
     * @param password 密码
     * @return
     */
    @Transactional
    public ResultVO checkLogin(String username, String password) {
        try {
            Example example = new Example(Users.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("username", username);
            Users user = usersMapper.selectOneByExample(example);
            if (user == null || user.getUserId() == null) {
                return new ResultVO(ResStatus.NO.getCode(), "用户名错误", null);
            }
            if (!MD5Utils.md5(password).equals(user.getPassword())) {
                return new ResultVO(ResStatus.NO.getCode(), "密码错误", null);
            }
//        用Base64Utils生成token字符串，但是规则太简单不适用
//        String token = Base64Utils.encode(username + password + new Date() + 123456);
//        用jwt生成token字符串
            HashMap<String, Object> map = new HashMap<>();
            map.put("key1", "value1");
            map.put("key2", "value2");
            JwtBuilder builder = Jwts.builder();
            String token = builder.setSubject(username)    //设置token数据
                    .setIssuedAt(new Date()) //设置开始时间
                    .setId(user.getUserId().toString())//设置用户id
                    .setClaims(map)  //map中可以存放其他数据
                    .setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000))//过期时间为一天
                    .signWith(SignatureAlgorithm.HS256, "123456") //设置加密方法和加密密码
                    .compact();  //生成字符串
            //把登录信息用token字符串为key存入redis中
            String userJson = objectMapper.writeValueAsString(user);
            stringRedisTemplate.boundValueOps(token).set(userJson,30,TimeUnit.MINUTES);
            return new ResultVO(ResStatus.OK.getCode(), token, user);
        } catch (Exception e) {
            return new ResultVO(ResStatus.NO.getCode(), e.getLocalizedMessage(), null);
        }

    }

    @Transactional
    public ResultVO userRegistration(String username, String password) {
        synchronized (this) {

            Example example = new Example(Users.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("username", username);
            List<Users> user = usersMapper.selectByExample(example);
            Users users = user.get(0);
            if (users != null && users.getUserId() != null) {
                return new ResultVO(ResStatus.ALREADY_EXISTS.getCode(), "用户已经存在", null);
            }
            String md5Password = MD5Utils.md5(password);
            users = new Users();
            users.setPassword(md5Password);
            users.setUsername(username);
            users.setUserImg("img/default.png");
            Integer insert = usersMapper.insert(users);
            if (insert == null) {
                return new ResultVO(ResStatus.NO.getCode(), "注册失败", null);
            }
            return new ResultVO(ResStatus.OK.getCode(), "注册成功", users);
        }
    }

}
